package com.sjgs.gis.common;

import com.sjgs.gis.domain.DataFile;
import com.sjgs.gis.domain.enumeration.DataFileType;
import com.sjgs.gis.fs.ChunkStore;
import com.sjgs.gis.fs.FSStore;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourceRegion;
import org.springframework.http.HttpHeaders;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

public class FileSystemFactory {

    private Map<String, Class<? extends FSStore>> registry = new HashMap<>();

    private static FileSystemFactory factory = null;

    public static FileSystemFactory instance() {
        try {
            //双重检查
            if (factory == null) {
                synchronized (FileSystemFactory.class) {
                    if (factory == null) {
                        factory = new FileSystemFactory();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return factory;
    }

    public static FileSystemFactory registry(String name, Class<? extends FSStore> clazz) {
        instance().getRegistry().put(name, clazz);
        return factory;
    }

    private FileSystemFactory() {

    }

    public Map<String, Class<? extends FSStore>> getRegistry() {
        return registry;
    }

    public void setRegistry(Map<String, Class<? extends FSStore>> registry) {
        this.registry = registry;
    }

    /**
     * 反射获取存储后端
     *
     * @param type
     * @return
     */
    public FSStore getFileSystem(DataFileType type) {
        if (instance().getRegistry().containsKey(type.name())) {
            Class<? extends FSStore> clazz = instance().getRegistry().get(type.name());
            return ApplicationContextHolder.getBean(clazz);
        } else {
            // 无注册后端返回本地存储
            return ApplicationContextHolder.getBean(instance().getRegistry().get(DataFileType.LOCAL.name()));
        }
    }

    public Mono<Resource> getResource(DataFile datafile) {
        DataFileType type = DataFileType.values()[datafile.getType()];
        return ((ChunkStore)getFileSystem(type)).getResourceByFkey(datafile);
    }

    public Mono<ResourceRegion> getResourceRegion(DataFile datafile, Mono<Resource> resourceMono, HttpHeaders headers) {
        DataFileType type = DataFileType.values()[datafile.getType()];
        return ((ChunkStore)getFileSystem(type)).getRegion(resourceMono, headers);
    }

}
